package com.ruoyi.wisdom.helper;

import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.tool.Md5Utils;
import com.ruoyi.common.utils.tool.TimerUtils;
import com.ruoyi.wisdom.constants.IotConstants;
import com.ruoyi.wisdom.domain.*;
import com.ruoyi.wisdom.domain.activity.DetectSource;
import com.ruoyi.wisdom.domain.other.OtherOptions;
import com.ruoyi.wisdom.domain.other.OtherTime;
import com.ruoyi.wisdom.domain.other.OtherUseTime;
import com.ruoyi.wisdom.event.MessagePushEvent;
import com.ruoyi.wisdom.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;

/**
 * 海康威视
 */
@Component
public class HkPick {

    @Autowired
    public IotConstants iotConstants;

    @Autowired
    private MessagePushEvent messagePushEvent;

    @Autowired
    private IIotPickSceneService iotPickSceneService;

    @Autowired
    private IIotPickGroupService iotPickGroupService;

    @Autowired
    private IIotPickDeviceService iotPickDeviceService;

    @Autowired
    private IIotPickRecordService iotPickRecordService;

    @Autowired
    private IIotCompanyUserService iotCompanyUserService;

    @Autowired
    private IIotStudentInfoService iotStudentInfoService;

    @Autowired
    private IIotSchoolClassesRelationService iotSchoolClassesRelationService;


    /**
     * 老师逻辑处理
     *
     * @param detectData
     */
    public void handleTeacher(DetectSource detectData) {
        // 查询用户资料
        IotCompanyUser ompanyUser = iotCompanyUserService.selectIotCompanyUserByUid(detectData.getUuid());
        if (ompanyUser != null) {
            // 查询设备
            IotPickDevice deviceParams = new IotPickDevice();
            deviceParams.setDeviceNo(detectData.getDeviceNo());
            IotPickDevice deviceInfo = iotPickDeviceService.selectIotPickDevice(deviceParams);
            if (deviceInfo != null) {
                // 查询场景
                List<IotPickScene> pickScenes = iotPickSceneService.selectIotPickSceneListByDeviceNo(detectData.getDeviceNo());
                System.out.println(pickScenes);
                if (pickScenes.size() > 0) {
                    for (IotPickScene pickScene : pickScenes) {
                        OtherOptions options = JSON.parseObject(pickScene.getOptions(), OtherOptions.class);
                        // 1、判断星期
                        if (options.getWeek() != null && !options.getWeek().equals("[]")) {
                            if (detectData.getWeek() == null) {
                                // 获取当前是星期几，返回值是 0（星期日）到 6（星期六）的整数， 实际用法是0是星期天
                                int dayOfWeek = TimerUtils.dateTimeToWeekIndex(detectData.getFaceTime());
                                detectData.setWeek(Integer.toString(dayOfWeek));
                            }
                            boolean inWeek = options.getWeek().contains(detectData.getWeek());
                            if (!inWeek) continue;
                        }

                        // 3、判断关联分组
                        OtherUseTime useTimeResult = new OtherUseTime();
                        // 4、判断时间：判断是否在合理的进出时间
                        useTimeResult = checkUseTime(pickScene, deviceInfo.getType(), detectData.getFaceTime());
                        if (!useTimeResult.getIsEnable()) continue;

                        // 4、查询识别时间间距: 多少分钟前
                        IotConfig iotConfig = iotConstants.getIotConfig();
                        long timestamp = TimerUtils.dateFormatToTime(detectData.getFaceTime(), "yyyy-MM-dd HH:mm:ss") - (60000 * iotConfig.getDetectTimeIntervals());
                        String startTime = TimerUtils.timeToDateTime(timestamp);

                        // 查询记录
                        IotPickRecord iotPickRecord = new IotPickRecord();
                        iotPickRecord.setUuid(detectData.getUuid());
                        iotPickRecord.setStartTime(startTime);
                        iotPickRecord.setType(deviceInfo.getType());
                        iotPickRecord.setSceneId(pickScene.getId().intValue());

                        List<IotPickRecord> pickRecords = iotPickRecordService.selectIotPickRecordList(iotPickRecord);
                        if (pickRecords.size() == 0) {
                            String hash = Md5Utils.encode32(detectData.getDeviceNo() + detectData.getFacecode() + detectData.getFaceTime());
                            IotPickRecord record = new IotPickRecord();
                            record.setComId(ompanyUser.getComId());
                            record.setUuid(ompanyUser.getUid());
                            record.setName(ompanyUser.getName());
                            record.setPersonType(IotConstants.USER_TYPE_TEACHER);
                            record.setType(deviceInfo.getType());
                            record.setFaceTime(detectData.getFaceTime());
                            record.setDeviceNo(detectData.getDeviceNo());
                            record.setSceneId(pickScene.getId().intValue());
                            record.setLocation(deviceInfo.getLocation());
                            record.setIsLate(useTimeResult.getIsLate());
                            record.setHash(hash);
                            record.setFacecode(detectData.getFacecode());
                            record.setMask(detectData.getMask());
                            record.setSimilar(detectData.getSimilar());
                            // 判断是否迟到
                            record.setIsLate(useTimeResult.getIsLate());
                            iotPickRecordService.insertIotPickRecord(record);
                        }
                    }
                }
            }
        }
    }

    /**
     * 学生逻辑处理
     *
     * @param detectData
     */
    public void handleStudent(DetectSource detectData) {
        // 查询学生资料
        IotStudentInfo studentInfo = iotStudentInfoService.selectIotStudentInfoById(detectData.getUuid());
        if (studentInfo != null) {
            // 查询设备
            IotPickDevice deviceParams = new IotPickDevice();
            deviceParams.setDeviceNo(detectData.getDeviceNo());
            IotPickDevice deviceInfo = iotPickDeviceService.selectIotPickDevice(deviceParams);
            if (deviceInfo != null) {
                // 查询场景
                List<IotPickScene> pickScenes = iotPickSceneService.selectIotPickSceneListByDeviceNo(detectData.getDeviceNo());
                if (pickScenes.size() > 0) {
                    for (IotPickScene pickScene : pickScenes) {
                        OtherOptions options = JSON.parseObject(pickScene.getOptions(), OtherOptions.class);
                        // 1、判断星期
                        if (options.getWeek() != null && !options.getWeek().equals("[]")) {
                            // 获取当前是星期几，返回值是 0（星期日）到 6（星期六）的整数， 实际用法是0是星期天
                            if (detectData.getWeek() == null) {
                                int dayOfWeek = TimerUtils.dateTimeToWeekIndex(detectData.getFaceTime());
                                detectData.setWeek(Integer.toString(dayOfWeek));
                            }
                            boolean inWeek = options.getWeek().contains(detectData.getWeek());
                            if (!inWeek) {
                                //System.out.println("不在星期里面，配置：" + options.getWeek() + ", 记录的星期：" + detectData.getWeek() + " ,记录时间：" + detectData.getFaceTime());
                                continue;
                            }
                        }

                        // 2、判断学生属性
                        if (options.getIsDormitory() != null && !options.getIsDormitory().equals("[]")) {
                            boolean inIsDormitory = options.getIsDormitory().contains(Integer.toString(studentInfo.getIsDormitory()));
                            if (!inIsDormitory) {
                                //System.out.println("不在学生属性内，配置属性：" + options.getIsDormitory() + " ,学生属性:" + studentInfo.getIsDormitory());
                                continue;
                            }
                        }

                        // 3、判断关联分组
                        OtherUseTime useTimeResult = new OtherUseTime();
                        if (options.getPickGroup() != null && !options.getPickGroup().equals("[]")) {
                            // 3.1 判断分组
                            Boolean inPickGroup = checkInGroup(studentInfo, options);
                            if (!inPickGroup) continue;
                            // 4、判断时间: 判断进出是否在有效的时间段内
                            useTimeResult = checkUseTime(pickScene, deviceInfo.getType(), detectData.getFaceTime());
                            if (!useTimeResult.getIsEnable()) continue;
                        } else {
                            // 4、判断时间：判断进出是否在有效的时间段内
                            useTimeResult = checkUseTime(pickScene, deviceInfo.getType(), detectData.getFaceTime());
                            if (!useTimeResult.getIsEnable()) continue;
                        }

                        // 4、查询识别时间间距: 多少分钟前
                        IotConfig iotConfig = iotConstants.getIotConfig();
                        long timestamp = TimerUtils.dateFormatToTime(detectData.getFaceTime(), "yyyy-MM-dd HH:mm:ss") - (60000 * iotConfig.getDetectTimeIntervals());
                        String startTime = TimerUtils.timeToDateTime(timestamp);

                        // 查询记录
                        IotPickRecord iotPickRecord = new IotPickRecord();
                        iotPickRecord.setStartTime(startTime);
                        iotPickRecord.setUuid(studentInfo.getId());
                        iotPickRecord.setType(deviceInfo.getType());
                        iotPickRecord.setSceneId(pickScene.getId().intValue());

                        List<IotPickRecord> pickRecords = iotPickRecordService.selectIotPickRecordList(iotPickRecord);
                        if (pickRecords.size() == 0) {
                            // 5、写出入记录
                            String hash = Md5Utils.encode32(detectData.getDeviceNo() + detectData.getFacecode() + detectData.getFaceTime());
                            IotPickRecord record = new IotPickRecord();
                            record.setComId(studentInfo.getComId());
                            record.setUuid(studentInfo.getId());
                            record.setName(studentInfo.getName());
                            record.setRelationId(studentInfo.getRelationId());
                            record.setPersonType(IotConstants.USER_TYPE_STUDENT);
                            record.setType(deviceInfo.getType());
                            record.setFaceTime(detectData.getFaceTime());
                            record.setDeviceNo(detectData.getDeviceNo());
                            record.setSceneId(pickScene.getId().intValue());
                            record.setLocation(deviceInfo.getLocation());
                            record.setIsLate(useTimeResult.getIsLate());
                            record.setHash(hash);
                            record.setFacecode(detectData.getFacecode());
                            record.setMask(detectData.getMask());
                            record.setSimilar(detectData.getSimilar());
                            // 判断是否迟到
                            record.setIsLate(useTimeResult.getIsLate());

                            int recordId = iotPickRecordService.insertIotPickRecord(record);
                            if (recordId > 0) {
                                IotPickRecord params = new IotPickRecord();
                                params.setHash(hash);
                                IotPickRecord row = iotPickRecordService.selectIotPickRecord(params);
                                if (row != null) {
                                    // 6、推送微信推送消息
                                    messagePushEvent.pushPickRecordMessageToStudent(row, pickScene);

                                    // 7、推送MQTT识别信息
                                }
                            }
                        } else {
                            //System.out.println(iotConfig.getDetectTimeIntervals()+"分钟内已经存在记录了");
                        }
                    }
                }
            }
        }
    }

    /**
     * 验证分组
     *
     * @param studentInfo
     * @param options
     * @return
     */
    private Boolean checkInGroup(IotStudentInfo studentInfo, OtherOptions options) {
        Boolean checkStatus = false;
        // 查询分组，循环变量
        String pickGroup = options.getPickGroup().replace("]", ",").replace("[", "");
        String[] groupIds = pickGroup.split(",");
        // 查询分组
        IotPickGroup groupParams = new IotPickGroup();
        groupParams.setIds(groupIds);
        List<IotPickGroup> groupList = iotPickGroupService.selectIotPickGroupList(groupParams);
        if (groupList.size() > 0) {
            for (IotPickGroup groupInfo : groupList) {
                // group_type:分组类型：1年级分组、2班级分组、3人员分组
                switch (groupInfo.getGroupType()) {
                    case 1:
                        checkStatus = checkGradeGroup(studentInfo, groupInfo);
                        break;

                    case 2:
                        checkStatus = checkClassGroup(studentInfo, groupInfo);
                        break;

                    case 3:
                        checkStatus = checkStudentGroup(studentInfo, groupInfo);
                        break;
                }
                // 当 checkStatus 为 true 时，跳出循环
                if (checkStatus) {
                    break;
                }
            }
        }
        return checkStatus;
    }

    /**
     * 验证年级分组
     *
     * @param studentInfo
     * @param groupInfo
     * @return
     */
    private Boolean checkGradeGroup(IotStudentInfo studentInfo, IotPickGroup groupInfo) {
        // 查询年级班级关系
        IotSchoolClassesRelation relation = iotSchoolClassesRelationService.selectIotSchoolClassesRelationById(studentInfo.getRelationId());
        if (relation != null) {
            String gradeId = relation.getGradeId().toString();
            // 使用 split 方法按逗号分割字符串
            String[] gradeIdArray = groupInfo.getGradeId().split(",");
            // 将数组转换为 List
            List<String> gradeIds = Arrays.asList(gradeIdArray);
            // 判断是否是否在字符序列中
            return gradeIds.contains(gradeId);
        }
        return false;
    }

    /**
     * 验证班级分组
     *
     * @param studentInfo
     * @param groupInfo
     * @return
     */
    private Boolean checkClassGroup(IotStudentInfo studentInfo, IotPickGroup groupInfo) {
        // 查询年级班级关系
        IotSchoolClassesRelation relation = iotSchoolClassesRelationService.selectIotSchoolClassesRelationById(studentInfo.getRelationId());
        if (relation != null) {
            String gradeId = relation.getGradeId().toString();
            String classId = relation.getClassId().toString();
            if (gradeId == groupInfo.getGradeId()) {
                // 使用 split 方法按逗号分割字符串
                String[] classIdArray = groupInfo.getClassId().split(",");
                // 将数组转换为 List
                List<String> classIds = Arrays.asList(classIdArray);
                // 判断是否是否在字符序列中
                return classIds.contains(classId);
            }
        }
        return false;
    }

    /**
     * 验证指定人员分组
     *
     * @param studentInfo
     * @param groupInfo
     * @return
     */
    private Boolean checkStudentGroup(IotStudentInfo studentInfo, IotPickGroup groupInfo) {
        if (groupInfo.getStudentId() != null) {
            String studentId = studentInfo.getId().toString();
            // 使用 split 方法按逗号分割字符串
            String[] studentIdArray = groupInfo.getStudentId().split(",");
            // 将数组转换为 List
            List<String> studentIds = Arrays.asList(studentIdArray);
            // 判断是否是否在字符序列中
            return studentIds.contains(studentId);
        }
        return false;
    }

    /**
     * 验证时间是否有效
     *
     * @param pickScene
     * @param type
     * @param faceTime
     * @return
     */
    private OtherUseTime checkUseTime(IotPickScene pickScene, int type, String faceTime) {
        OtherUseTime useTimeResult = new OtherUseTime();
        try {
            // 定义日期时间格式
            DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
            // 解析原始时间
            LocalDateTime dateTime = LocalDateTime.parse(faceTime, inputFormatter);
            // 格式化为时间部分 HH:mm:ss
            String faceTimeOnly = dateTime.format(outputFormatter);
            // faceTime转化为时间戳
            LocalTime faceTimeLocal = LocalTime.parse(faceTimeOnly, outputFormatter);

            String useTimes = "";
            if (type == IotConstants.TYPE_COME) {
                useTimes = pickScene.getComeTime();
            } else {
                useTimes = pickScene.getOutTime();
            }
            ObjectMapper objectMapper = new ObjectMapper();
            List<OtherTime> options = objectMapper.readValue(useTimes, objectMapper.getTypeFactory().constructCollectionType(List.class, OtherTime.class));
            for (OtherTime option : options) {
                LocalTime startTime = LocalTime.parse(option.getStartTime(), outputFormatter);
                LocalTime endTime = LocalTime.parse(option.getEndTime(), outputFormatter);

                if ((faceTimeLocal.isAfter(startTime) || faceTimeLocal.equals(startTime)) && (faceTimeLocal.isBefore(endTime) || faceTimeLocal.equals(endTime))) {
                    useTimeResult.setIsEnable(true);
                    // 判断是否迟到
                    if (option.getLateTime() != null) {
                        LocalTime lateTime = LocalTime.parse(option.getLateTime(), outputFormatter);
                        if (faceTimeLocal.isAfter(lateTime)) {
                            useTimeResult.setIsLate(1);
                        }
                    }

                    break;
                }
            }
            return useTimeResult;
        } catch (Exception e) {
            e.printStackTrace();
            return useTimeResult;
        }
    }
}
